<template>
  <div ref="wrapRef" :class="getWrapperClass">
    <BasicForm :class="{ 'table-search-area-hidden': !getBindValues.formConfig?.schemas?.length }" submitOnReset
      v-bind="getFormProps" v-if="getBindValues.useSearchForm" :tableAction="tableAction" @register="registerForm"
      @submit="handleSearchInfoChange" @advanced-change="redoHeight">
      <template #[replaceFormSlotKey(item)]="data" v-for="item in getFormSlotKeys">
        <slot :name="item" v-bind="data || {}"></slot>
      </template>
    </BasicForm>

    <a-form-item-rest>
      <a-form-item>
        <Table ref="tableElRef" v-bind="getBindValues" :rowClassName="getRowClassName" v-show="getEmptyDataIsShowTable"
          @resizeColumn="handleResizeColumn" @change="handleTableChange">
          <!-- 原生插槽传递 -->
          <template #[item]="data" v-for="item in slotNamesGroup.native" :key="item">
            <template v-if="item === 'headerCell'">
              <CustomSelectHeader v-if="isCustomSelection(data.column)" v-bind="selectHeaderProps" />
              <slot v-else :name="item" v-bind="data || {}"></slot>
            </template>
            <slot v-else :name="item" v-bind="data || {}"></slot>
          </template>

          <!-- 表头单元格插槽 -->
          <template #headerCell="{ column }">
            <CustomSelectHeader v-if="isCustomSelection(column)" v-bind="selectHeaderProps" />
            <HeaderCell v-else :column="column" />
          </template>

          <!-- 主体单元格插槽 -->
          <template #bodyCell="data">
            <template v-if="data.column?.slotsBak?.customRender">
              <slot :name="data.column.slotsBak.customRender" v-bind="data || {}"></slot>
            </template>
            <template v-else>
              <slot name="bodyCell" v-bind="data || {}"></slot>
            </template>
          </template>

          <!-- 表尾合计插槽 -->
          <template v-if="showSummaryRef && !getBindValues.showSummary" #summary="data">
            <slot name="summary" v-bind="data || {}">
              <TableSummary :data="data || {}" v-bind="getSummaryProps" />
            </slot>
          </template>
        </Table>
      </a-form-item>
    </a-form-item-rest>
  </div>
</template>

<script lang="ts">
import type { BasicTableProps, TableActionType, SizeType, ColumnChangeParam, BasicColumn } from './types/table';

import { defineComponent, ref, computed, unref, toRaw, inject, watchEffect, nextTick } from 'vue';
import { Table } from 'ant-design-vue';
import { BasicForm, useForm } from '/@/components/Form/index';
import { PageWrapperFixedHeightKey } from '/@/components/Page/injectionKey';
import CustomSelectHeader from './components/CustomSelectHeader.vue'
import HeaderCell from './components/HeaderCell.vue';
import TableSummary from './components/TableSummary';
import { InnerHandlers } from './types/table';
import { usePagination } from './hooks/usePagination';
import { useColumns } from './hooks/useColumns';
import { useDataSource } from './hooks/useDataSource';
import { useLoading } from './hooks/useLoading';
import { useCustomSelection } from "./hooks/useCustomSelection";
import { useTableScroll } from './hooks/useTableScroll';
import { useCustomRow } from './hooks/useCustomRow';
import { useTableStyle } from './hooks/useTableStyle';
import { useTableHeader } from './hooks/useTableHeader';
import { useTableExpand } from './hooks/useTableExpand';
import { createTableContext } from './hooks/useTableContext';
import { useTableFooter } from './hooks/useTableFooter';
import { useTableForm } from './hooks/useTableForm';
import { useDesign } from '/@/hooks/web/useDesign';

import { omit, pick } from 'lodash-es';
import { basicProps } from './props';
import { isFunction } from '/@/utils/is';
import { warn } from '/@/utils/log';

export default defineComponent({
  components: {
    Table,
    BasicForm,
    HeaderCell,
    TableSummary,
    CustomSelectHeader,
  },
  props: {
    ...basicProps,
    minColumnWidth: {
      type: Number,
      default: 80, // 最小列宽限制
    },
    persistColumnWidth: {
      type: Boolean,
      default: true, // 是否持久化保存列宽
    },
    columnWidthStorageKey: {
      type: String,
      default: 'basic_table_column_width', // 本地存储键名前缀
    },
  },
  emits: [
    'fetch-success',
    'fetch-error',
    'selection-change',
    'register',
    'row-click',
    'row-dbClick',
    'row-contextmenu',
    'row-mouseenter',
    'row-mouseleave',
    'edit-end',
    'edit-cancel',
    'edit-row-end',
    'edit-change',
    'expanded-rows-change',
    'change',
    'columns-change',
    'table-redo',
    'column-resize',
  ],
  setup(props, { attrs, emit, slots, expose }) {
    const tableElRef = ref(null);
    const tableData = ref<Recordable[]>([]);
    const wrapRef = ref(null);
    const innerPropsRef = ref<Partial<BasicTableProps>>();

    const { prefixCls } = useDesign('basic-table');
    const [registerForm, formActions] = useForm();

    // 存储列宽的工具方法
    const getStorageKey = (columnKey: string) => {
      return `${props.columnWidthStorageKey}_${columnKey}`;
    };

    const getSavedColumnWidth = (columnKey: string) => {
      if (!props.persistColumnWidth) return null;
      const saved = localStorage.getItem(getStorageKey(columnKey));
      return saved ? Number(saved) : null;
    };

    const saveColumnWidth = (columnKey: string, width: number) => {
      if (props.persistColumnWidth && columnKey) {
        localStorage.setItem(getStorageKey(columnKey), String(width));
      }
    };

    const getProps = computed(() => {
      return { ...props, ...unref(innerPropsRef) } as BasicTableProps;
    });

    const isFixedHeightPage = inject(PageWrapperFixedHeightKey, false);
    watchEffect(() => {
      unref(isFixedHeightPage) &&
        props.canResize &&
        warn("'canResize' of BasicTable may not work in PageWrapper with 'fixedHeight'");
    });

    const { getLoading, setLoading } = useLoading(getProps);
    const { getPaginationInfo, getPagination, setPagination, setShowPagination, getShowPagination } = usePagination(getProps);

    // 自定义选择列逻辑
    const childrenColumnName = computed(() => getProps.value.childrenColumnName || 'children');
    const {
      getRowSelection,
      getSelectRows,
      getSelectRowKeys,
      setSelectedRowKeys,
      getRowSelectionRef,
      selectHeaderProps,
      isCustomSelection,
      handleCustomSelectColumn,
      clearSelectedRowKeys,
      deleteSelectRowByKey,
      getExpandIconColumnIndex,
    } = useCustomSelection(
      getProps,
      emit,
      wrapRef,
      getPaginationInfo,
      tableData,
      childrenColumnName
    );

    // 数据源逻辑
    const {
      handleTableChange: onTableChange,
      getDataSourceRef,
      getDataSource,
      getRawDataSource,
      setTableData,
      updateTableDataRecord,
      deleteTableDataRecord,
      insertTableDataRecord,
      findTableDataRecord,
      fetch,
      getRowKey,
      reload,
      getAutoCreateKey,
      updateTableData,
    } = useDataSource(
      getProps,
      {
        tableData,
        getPaginationInfo,
        setLoading,
        setPagination,
        validate: formActions.validate,
        clearSelectedRowKeys,
      },
      emit
    );

    function handleTableChange(...args) {
      onTableChange.call(undefined, ...args);
      emit('change', ...args);
      const { onChange } = unref(getProps);
      onChange && isFunction(onChange) && onChange.call(undefined, ...args);
    }

    // 列处理逻辑
    const { getViewColumns, getColumns, setCacheColumnsByField, setColumns, getColumnsRef, getCacheColumns } = useColumns(
      getProps,
      getPaginationInfo,
      handleCustomSelectColumn,
    );

    // 核心修改：优化列宽调整逻辑（保留拖拽功能，解决同步问题）
    const handleResizeColumn = (width: number, column: BasicColumn) => {
      if (!column) return;

      // 1. 限制最小宽度
      const minWidth = props.minColumnWidth;
      const adjustedWidth = Math.max(width, minWidth);
      const columnKey = column.dataIndex || column.key;

      // 2. 找到对应列并更新宽度配置
      const columns = getColumns();
      const targetColIndex = columns.findIndex(
        col => (col.dataIndex || col.key) === columnKey
      );

      if (targetColIndex > -1) {
        // 3. 更新列配置（触发响应式更新）
        const newColumns = [...columns];
        newColumns[targetColIndex] = { ...newColumns[targetColIndex], width: adjustedWidth };
        setColumns(newColumns);

        // 4. 保存宽度
        saveColumnWidth(columnKey, adjustedWidth);

        // 5. 关键优化：使用requestAnimationFrame确保UI同步更新
        // 避免强制重渲染导致的拖拽失效，改为更柔和的同步方式
        nextTick(() => {
          const tableEl = unref(tableElRef);
          if (tableEl?.$el) {
            // 手动同步表头和单元格宽度（针对AntD的渲染机制）
            const headerCell = tableEl.$el.querySelector(`th[data-index="${columnKey}"]`);
            const bodyCells = tableEl.$el.querySelectorAll(`td[data-index="${columnKey}"]`);

            if (headerCell && bodyCells.length) {
              // 直接同步DOM宽度（绕过Vue响应式更新的延迟）
              const headerWidth = headerCell.offsetWidth;
              bodyCells.forEach(cell => {
                cell.style.width = `${headerWidth}px`;
                cell.style.minWidth = `${headerWidth}px`;
              });
            }
          }
        });

        // 6. 触发事件
        emit('column-resize', {
          column: { ...column },
          width: adjustedWidth,
          originalWidth: width,
        });
      }
    };

    // 处理列数据
    const processedColumnData = computed(() => {
      const columns = getViewColumns.value as BasicColumn[];
      return columns.map((item) => {
        const columnKey = item.dataIndex || item.key;
        const savedWidth = getSavedColumnWidth(columnKey);

        return {
          ...item,
          resizable: item.resizable ?? true, // 确保拖拽功能开启
          width: savedWidth ?? item.width,
          minWidth: item.minWidth ?? props.minColumnWidth,
        };
      });
    });

    // 优化滚动配置（针对固定列场景）
    const { getScrollRef, redoHeight } = useTableScroll(getProps, tableElRef, getColumnsRef, getRowSelectionRef, getDataSourceRef);

    const { customRow } = useCustomRow(getProps, {
      setSelectedRowKeys,
      getSelectRowKeys,
      clearSelectedRowKeys,
      getAutoCreateKey,
      emit,
    });

    const { getRowClassName } = useTableStyle(getProps, prefixCls);
    const { getExpandOption, expandAll, collapseAll } = useTableExpand(getProps, tableData, emit);

    const handlers: InnerHandlers = {
      onColumnsChange: (data: ColumnChangeParam[]) => {
        emit('columns-change', data);
        unref(getProps).onColumnsChange?.(data);
      },
    };

    const { getHeaderProps } = useTableHeader(getProps, slots, handlers);
    const getSummaryProps = computed(() => {
      return pick(unref(getProps), ['summaryFunc', 'summaryData', 'hasExpandedRow', 'rowKey']);
    });
    const getIsEmptyData = computed(() => {
      return (unref(getDataSourceRef) || []).length === 0;
    });
    const showSummaryRef = computed(() => {
      const summaryProps = unref(getSummaryProps);
      return (summaryProps.summaryFunc || summaryProps.summaryData) && !unref(getIsEmptyData);
    });

    const { getFooterProps } = useTableFooter(getProps, slots, getScrollRef, tableElRef, getDataSourceRef);
    const { getFormProps, replaceFormSlotKey, getFormSlotKeys, handleSearchInfoChange } = useTableForm(getProps, slots, fetch, getLoading);

    // 表格绑定属性
    const getBindValues = computed(() => {
      const dataSource = unref(getDataSourceRef);
      let propsData: Recordable = {
        ...attrs,
        customRow,
        ...unref(getProps),
        ...unref(getHeaderProps),
        scroll: unref(getScrollRef),
        loading: unref(getLoading),
        tableLayout: 'auto',
        rowSelection: unref(getRowSelectionRef),
        rowKey: unref(getRowKey),
        columns: toRaw(unref(processedColumnData)),
        pagination: toRaw(unref(getPaginationInfo)),
        dataSource,
        footer: unref(getFooterProps),
        ...unref(getExpandOption),
        expandIconColumnIndex: getExpandIconColumnIndex.value,
      };

      delete propsData.rowSelection;
      !propsData.isTreeTable && delete propsData.expandIconColumnIndex;
      propsData.expandedRowKeys === null && delete propsData.expandedRowKeys;
      propsData = omit(propsData, ['class', 'onChange']);
      return propsData;
    });

    // 样式相关
    const getMaxColumnWidth = computed(() => {
      const values = unref(getBindValues);
      return values.maxColumnWidth > 0 ? values.maxColumnWidth + 'px' : null;
    });
    const getWrapperClass = computed(() => {
      const values = unref(getBindValues);
      return [
        prefixCls,
        attrs.class,
        {
          [`${prefixCls}-form-container`]: values.useSearchForm,
          [`${prefixCls}--inset`]: values.inset,
          [`${prefixCls}-col-max-width`]: getMaxColumnWidth.value != null,
          [`${prefixCls}--show-summary`]: values.showSummary,
        },
      ];
    });
    const getEmptyDataIsShowTable = computed(() => {
      const { emptyDataIsShowTable, useSearchForm } = unref(getProps);
      return emptyDataIsShowTable || !useSearchForm || !!unref(getDataSourceRef).length;
    });

    // 表格操作方法
    function setProps(props: Partial<BasicTableProps>) {
      innerPropsRef.value = { ...unref(innerPropsRef), ...props };
    }

    const tableAction: TableActionType & { resetColumnWidth: (columnKey?: string) => void } = {
      reload,
      getSelectRows,
      clearSelectedRowKeys,
      getSelectRowKeys,
      deleteSelectRowByKey,
      setPagination,
      setTableData,
      updateTableDataRecord,
      deleteTableDataRecord,
      insertTableDataRecord,
      findTableDataRecord,
      redoHeight,
      setSelectedRowKeys,
      setColumns,
      setLoading,
      getDataSource,
      getRawDataSource,
      setProps,
      getRowSelection,
      getPaginationRef: getPagination,
      getColumns,
      getCacheColumns,
      emit,
      updateTableData,
      setShowPagination,
      getShowPagination,
      setCacheColumnsByField,
      expandAll,
      collapseAll,
      getSize: () => unref(getBindValues).size as SizeType,
      resetColumnWidth: (columnKey?: string) => {
        const columns = getColumns();
        const newColumns = columns.map(col => {
          const key = col.dataIndex || col.key;
          if (!columnKey || key === columnKey) {
            localStorage.removeItem(getStorageKey(key));
            return { ...col, width: col.defaultWidth ?? col.width };
          }
          return col;
        });
        setColumns(newColumns);
      },
    };

    createTableContext({ ...tableAction, wrapRef, getBindValues });

    // 插槽分组逻辑
    const slotNamesGroup = computed<{ native: string[]; custom: string[] }>(() => {
      const native: string[] = [];
      const custom: string[] = [];
      const columns = unref<BasicColumn[]>(getViewColumns);
      const allCustomRender = columns.map(col => col.slotsBak?.customRender).filter(Boolean);
      for (const name of Object.keys(slots)) {
        if (['bodyCell'].includes(name)) continue;
        allCustomRender.includes(name) ? custom.push(name) : native.push(name);
      }
      return { native, custom };
    });

    // 默认展开逻辑
    nextTick(() => {
      getProps.value.defaultExpandAllRows && expandAll();
    });

    expose(tableAction);
    emit('register', tableAction, formActions);

    return {
      tableElRef,
      getBindValues,
      getLoading,
      registerForm,
      handleSearchInfoChange,
      getEmptyDataIsShowTable,
      handleTableChange,
      getRowClassName,
      wrapRef,
      tableAction,
      redoHeight,
      handleResizeColumn,
      getFormProps: getFormProps as any,
      replaceFormSlotKey,
      getFormSlotKeys,
      getWrapperClass,
      getMaxColumnWidth,
      columns: getViewColumns,
      selectHeaderProps,
      isCustomSelection,
      slotNamesGroup,
      getSummaryProps,
      showSummaryRef,
      getViewColumns,
      processedColumnData
    };
  },
});
</script>

<style lang="less">
@border-color: #cecece4d;
@prefix-cls: ~'@{namespace}-basic-table';
@drag-handle-color: #ddd;
@drag-active-color: @primary-color;

[data-theme='dark'] {

  .ant-table-tbody>tr:hover.ant-table-row-selected>td,
  .ant-table-tbody>tr.ant-table-row-selected td {
    background-color: #262626;
  }

  @drag-handle-color: #444;
  @drag-active-color: #40a9ff;
}

.@{prefix-cls} {
  max-width: 100%;

  &-row__striped {
    td {
      background-color: @app-content-background;
    }
  }

  >.table-search-area-hidden {
    display: none;
  }

  &-form-container {
    padding: 10px;

    .ant-form {
      padding: 12px 10px 6px 10px;
      margin-bottom: 8px;
      background-color: @component-background;
      border-radius: 2px;
    }
  }

  .ant-tag {
    margin-right: 0;
  }

  .ant-picker-preset {
    .ant-tag {
      margin-right: 8px !important;
    }
  }

  .ant-table-wrapper {
    padding: 6px;
    background-color: @component-background;
    border-radius: 2px;
  }

  .ant-table {
    width: 100%;
    overflow-x: hidden;

    // 关键：移除所有宽度相关的过渡动画，避免延迟感
    .ant-table-cell {
      transition: none !important;
    }

    // 拖拽手柄样式
    .ant-table-header .ant-table-cell {
      .ant-table-column-sorter {
        position: relative;
        padding-right: 12px;

        &::after {
          content: '';
          position: absolute;
          right: 0;
          top: 50%;
          transform: translateY(-50%);
          width: 4px;
          height: 16px;
          border-radius: 2px;
          background-color: @drag-handle-color;
          cursor: col-resize;
          opacity: 0;
          transition: opacity 0.2s;
        }

        &:hover::after {
          opacity: 1;
        }
      }
    }

    // 拖拽中的列样式
    &-column-resizing {
      background-color: @drag-active-color;
      opacity: 0.5;
      pointer-events: none;
    }

    // 固定列同步样式
    &-fixed-left,
    &-fixed-right {
      .ant-table-cell {
        transition: none !important;
      }
    }
  }

  .ant-pagination {
    margin: 10px 0 0 0;
  }

  .ant-table-footer {
    padding: 0;

    td {
      padding: 12px 8px;
    }
  }

  .alert {
    height: 38px;
  }

  &--inset {
    .ant-table-wrapper {
      padding: 0;
    }
  }

  &-col-max-width {

    .ant-table-thead tr th,
    .ant-table-tbody tr td {
      max-width: v-bind(getMaxColumnWidth);
    }
  }

  >.ant-form-item {
    margin-bottom: 0;
  }
}
</style>
